(************************************************************************)
(*                                                                      *)
(*    Release 3.00                                                      *)
(*                                                                      *)
(*    CoreRTL - Common run-time support module.                         *)
(*                                                                      *)
(*    Copyright (C) 1989, 1990 Jensen and Partners. All Rights Reserved *)
(*    Written by Simon Knight.                                          *)
(*                                                                      *)
(*    Copyright (C) 1991 Psion PLC. All Rights Reserved                 *)
(*    Modified by NSM.                                                  *)
(*                                                                      *)
(************************************************************************)

include "corelib.inc"
include "epocdefs.inc"

module CoreRTL

(****************************************************************************)
section
segment _TEXT(CODE,28H);

public N$StdRet :

    pop  ax
    pop  bx
    pop  cx
    pop  dx
    pop  si
    pop  di
    mov  sp, bp
    pop  bp
    ret  0

section
segment _TEXT(CODE,28H);


public N$UnsMol : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
public N$SgnMol :
(* Unsigned/signed multiplication *)
(* On overflow: modulus 2^32 wrap-around *)
  push bp
  mov  bp,sp

  mov  ax,[bp][High1]
  and  ax,ax
  jnz  UnsMol2
  add  ax,[bp][High2]
  jnz  UnsMol1
  mov  ax,[bp][Low1]
  mul  word [bp][Low2]

  pop  bp
  ret  near  8

UnsMol1:
  mul  word [bp][Low1]
  mov  dx,[bp][Low1]
  mov  bp,[bp][Low2]
  xchg bp,ax
  mul  dx
  add  dx,bp
  pop  bp
  ret  near  8

UnsMol2:
  mov  dx,[bp][High2]
  and  dx,dx
  jnz  UnsMol3
  mul  word [bp][Low2]
  mov  dx,[bp][Low1]
  mov  bp,[bp][Low2]
  xchg bp,ax
  mul  dx
  add  dx,bp
  pop  bp
  ret  near  8

UnsMol3:
  push cx
  mul  word [bp][Low2]
  mov  cx,ax
  mov  ax,[bp][High2]
  mul  word [bp][Low1]
  add  cx,ax
  mov  ax,[bp][Low1]
  mul  word [bp][Low2]
  add  dx,cx
  pop  cx
  pop  bp
  ret  near  8

section
segment _TEXT(CODE,28H);

extrn N$UnsMul

public N$SgnDiv : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Signed division *)
(*On overflow: result MAXINT, OF set *)
  push bp
  mov  bp,sp
  push cx
  push si

  xor  si,si
(* DIV / 0 Test *)
  mov  dx,[bp][High2]
  or   dx,[bp][Low2]
  jnz  DivOK
  extrn N$CnsDiv
  add  sp, 6
  jmp  N$CnsDiv
DivOK:
  mov  dx,[bp][High1]
  and  dx,dx
  jge  SgnDiv5
  not  si
  neg  dx
  neg  word [bp][Low1]
  sbb  dx,0
  mov  [bp][High1],dx
SgnDiv5:
  mov  dx,[bp][High2]
  and  dx,dx
  jg   SgnDiv1
  jz   SgnDiv6
  not  si
  neg  dx
  neg  word [bp][Low2]
  sbb  dx,0
  mov  [bp][High2],dx
  jnz  SgnDiv1

SgnDiv6:
  mov  cx,[bp][Low2]
  jcxz SgnDiv0
  mov  dx,[bp][High1]
  cmp  dx,cx
  jae  SgnDivA
  mov  ax,[bp][Low1]
  div  cx
  xor  dx,dx

SgnDiv9:
  add  ax,si
  adc  dx,si
  xor  ax,si
  xor  dx,si

SgnDiv7:
  pop  si
  pop  cx
  pop  bp
  ret  near  8

SgnDivA:
  mov  ax,dx
  xor  dx,dx
  div  cx
  mov  cx,ax
  mov  ax,[bp][Low1]
  div  word [bp][Low2]
  mov  dx,cx
  jmp  SgnDiv9

SgnDiv1:
  push bx
  mov  cx,dx
  mov  bx,[bp][Low2]
  mov  dx,[bp][High1]
  mov  ax,[bp][Low1]
  push cx
  push bx
SgnDiv2:
  shr  dx,1
  rcr  ax,1
  shr  cx,1
  rcr  bx,1
  and  cx,cx
  jnz  SgnDiv2
  div  bx
  mov  bx,ax
  push cx
  push ax
  call near N$UnsMul
  jo   SgnDiv3
  cmp  dx,[bp][High1]
  ja   SgnDiv3
  jb   SgnDiv4
  cmp  ax,[bp][Low1]
  jbe  SgnDiv4
SgnDiv3:
  dec  bx
SgnDiv4:
  mov  ax,bx
  xor  dx,dx
  pop  bx
  jmp  SgnDiv9

SgnDiv0:
  mov  al,100
  add  al,al
  mov  ax,0FFFFH
  mov  dx,07FFFH
  jmp  SgnDiv7

section
segment _TEXT(CODE,28H);

extrn N$UnsMul

public N$UnsDiv : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Unsigned division *)
(*On overflow: result MAXCARD, OF set *)
  push bp
  mov  bp,sp
  push cx

(* DIV / 0 Test *)
  mov  cx,[bp][High2]
  or   cx,[bp][Low2]
  jnz  DivOK
  extrn N$CnsDiv
  add  sp, 4
  jmp  N$CnsDiv
DivOK:
  mov  cx,[bp][High2]
  and  cx,cx
  jnz  UnsDiv1
  add  cx,[bp][Low2]
  jz   UnsDiv0

  mov  dx,[bp][High1]
  cmp  dx,cx
  jae  UnsDiv7    (*!!!!New special case *)
  mov  ax,[bp][Low1]
  div  cx
  xor  dx,dx

UnsDiv8:
  and  ax,ax
UnsDiv9:
  pop  cx
  pop  bp
  ret  near  8

UnsDiv7:
  mov  ax,dx
  xor  dx,dx
  div  cx
  mov  cx,ax
  mov  ax,[bp][Low1]
  div  word [bp][Low2]
  mov  dx,cx
  jmp  UnsDiv8

UnsDiv1:
  push bx
  mov  dx,[bp][High1]
  mov  ax,[bp][Low1]
  mov  bx,[bp][Low2]
  push cx
  push bx
UnsDiv2:
  shr  dx,1
  rcr  ax,1
  shr  cx,1
  rcr  bx,1
  and  cx,cx
  jnz  UnsDiv2
  div  bx
  mov  bx,ax
  push cx
  push ax
  call near N$UnsMul
  jo   UnsDiv3
  cmp  dx,[bp][High1]
  jb   UnsDiv4
  ja   UnsDiv3
  cmp  ax,[bp][Low1]
  jbe  UnsDiv4
UnsDiv3:
  dec  bx
UnsDiv4:
  mov  ax,bx
  xor  dx,dx
  pop  bx
  jmp  UnsDiv8

UnsDiv0:
  mov  al,100
  add  al,al
  mov  ax,0FFFFH
  mov  dx,ax
  jmp  UnsDiv9


section
segment _TEXT(CODE,28H);

extrn N$UnsMul

public N$SgnRem : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Signed remainder *)
(*On overflow: result 0, OF set *)
  push bp
  mov  bp,sp
  push cx
  push si

(* DIV / 0 Test *)
  mov  dx,[bp][High2]
  or   dx,[bp][Low2]
  jnz  DivOK
  extrn N$CnsDiv
  add  sp, 6
  jmp  N$CnsDiv
DivOK:
  xor  si,si
  mov  dx,[bp][High1]
  and  dx,dx
  jge  SgnRem5
  not  si
  neg  dx
  neg  word [bp][Low1]
  sbb  dx,0
  mov  [bp][High1],dx
SgnRem5:
  mov  dx,[bp][High2]
  and  dx,dx
  jg   SgnRem1
  jz   SgnRem6
  neg  dx
  neg  word [bp][Low2]
  sbb  dx,0
  mov  [bp][High2],dx
  jnz  SgnRem1

SgnRem6:
  mov  cx,[bp][Low2]
  jcxz SgnRem0
  mov  ax,[bp][High1]
  div  cx
  mov  ax,[bp][Low1]
  div  cx
  mov  ax,dx
  xor  dx,dx

SgnRem9:
  add  ax,si
  adc  dx,si
  xor  ax,si
  xor  dx,si

SgnRem7:
  pop  si
  pop  cx
  pop  bp
  ret  near  8

SgnRem1:
  push bx
  mov  cx,dx
  mov  bx,[bp][Low2]
  mov  dx,[bp][High1]
  mov  ax,[bp][Low1]
  push cx
  push bx
SgnRem2:
  shr  dx,1
  rcr  ax,1
  shr  cx,1
  rcr  bx,1
  and  cx,cx
  jnz  SgnRem2
  div  bx
  push cx
  push ax
  call near N$UnsMul
  cmp  dx,[bp][High1]
  ja   SgnRem3
  jb   SgnRem4
  cmp  ax,[bp][Low1]
  jbe  SgnRem4
SgnRem3:
  sub  ax,[bp][Low2]
  sbb  dx,[bp][High2]
SgnRem4:
  sub  ax,[bp][Low1]
  sbb  dx,[bp][High1]
  neg  dx
  neg  ax
  sbb  dx,cx
  pop  bx
  jmp  SgnRem9

SgnRem0:
  sub  dx,dx
  mov  al,100
  add  al,al
  mov  ax,dx
  jmp  SgnRem7

section
segment _TEXT(CODE,28H);

extrn N$UnsMul

public N$SgnMod : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Signed modulus *)
(*On overflow: result 0, OF set *)
  push bp
  mov  bp,sp
  push cx
  push bx

(* DIV / 0 Test *)
  mov  dx,[bp][High2]
  or   dx,[bp][Low2]
  jnz  DivOK
  extrn N$CnsDiv
  add  sp, 6
  jmp  N$CnsDiv
DivOK:
  mov  dx,[bp][High1]
  mov  bh, dh
  and  dx,dx
  jge  SgnMod5
  neg  dx
  neg  word [bp][Low1]
  sbb  dx,0
  mov  [bp][High1],dx
SgnMod5:
  mov  dx,[bp][High2]
  mov  bl,dh
  and  dx,dx
  jg   SgnMod1
  jz   SgnMod6
  neg  dx
  neg  word [bp][Low2]
  sbb  dx,0
  mov  [bp][High2],dx
  jnz  SgnMod1

SgnMod6:
  mov  cx,[bp][Low2]
  jcxz SgnMod0
  mov  ax,[bp][High1]
  div  cx
  mov  ax,[bp][Low1]
  div  cx
  mov  ax,dx
  xor  dx,dx

SgnMod9:
  mov cx,ax
  or  cx,dx
  jz SgnMod7
  xor bh,bl
  jge SgnMod10
  sub  ax,[bp][Low2]
  sbb  dx,[bp][High2]
  not bl
SgnMod10:
  shl bl,1
  jnc SgnMod7
  neg dx
  neg ax
  sbb dx,0
SgnMod7:
  pop  bx
  pop  cx
  pop  bp
  ret near  8

SgnMod1:
  push si
  mov  cx,dx
  mov  si,[bp][Low2]
  mov  dx,[bp][High1]
  mov  ax,[bp][Low1]
  push cx
  push si
SgnMod2:
  shr  dx,1
  rcr  ax,1
  shr  cx,1
  rcr  si,1
  and  cx,cx
  jnz  SgnMod2
  div  si
  push cx
  push ax
  call near N$UnsMul
  cmp  dx,[bp][High1]
  ja   SgnMod3
  jb   SgnMod4
  cmp  ax,[bp][Low1]
  jbe  SgnMod4
SgnMod3:
  sub  ax,[bp][Low2]
  sbb  dx,[bp][High2]
SgnMod4:
  sub  ax,[bp][Low1]
  sbb  dx,[bp][High1]
  neg  dx
  neg  ax
  sbb  dx,cx
  pop  si
  jmp  SgnMod9

SgnMod0: (* overflow *)
  sub  dx,dx
  mov  al,100
  add  al,al
  mov  ax,dx
  jmp  SgnMod7

section
segment _TEXT(CODE,28H);

extrn N$UnsMul

public N$UnsRem : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Unsigned remainder/modulus *)
(*On overflow: result 0, OF set *)
  push bp
  mov  bp,sp
  push cx

(* DIV / 0 Test *)
  mov  cx,[bp][High2]
  or   cx,[bp][Low2]
  jnz  DivOK
  extrn N$CnsDiv
  add  sp, 4
  jmp  N$CnsDiv
DivOK:
  mov  cx,[bp][High2]
  and  cx,cx
  jnz  UnsRem1
  add  cx,[bp][Low2]
  jz   UnsRem0
  mov  ax,[bp][High1]
  xor  dx,dx
  div  cx
  mov  ax,[bp][Low1]
  div  cx
  mov  ax,dx
  xor  dx,dx

UnsRem9:
  pop  cx
  pop  bp
  ret  near  8

UnsRem1:
  push bx
  mov  dx,[bp][High1]
  mov  ax,[bp][Low1]
  mov  bx,[bp][Low2]
  push cx
  push bx
UnsRem2:
  shr  dx,1
  rcr  ax,1
  shr  cx,1
  rcr  bx,1
  and  cx,cx
  jnz  UnsRem2
  div  bx
  sub  ax,1
  adc  ax,0
  push cx
  push ax
  call near N$UnsMul
  add  ax,[bp][Low2]
  adc  dx,[bp][High2]
  jc   UnsRem3
  cmp  dx,[bp][High1]
  jb   UnsRem4
  ja   UnsRem3
  cmp  ax,[bp][Low1]
  jbe  UnsRem4
UnsRem3:
  sub  ax,[bp][Low2]
  sbb  dx,[bp][High2]
UnsRem4:
  sub  ax,[bp][Low1]
  sbb  dx,[bp][High1]
  neg  dx
  neg  ax
  sbb  dx,cx
  and  ax,ax
  pop  bx
  jmp  UnsRem9

UnsRem0:
  xor  dx,dx
  mov  al,100
  add  al,al
  mov  ax,dx
  jmp  UnsRem9

section
segment _TEXT(CODE,28H);

public N$UnsMul : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Unsigned multiplication *)
(*On overflow: result MAXCARD, OF set *)
  push bp
  mov  bp,sp

  mov  ax,[bp][High1]
  and  ax,ax
  jnz  UnsMul1
  add  ax,[bp][High2]
  jnz  UnsMul2
  mov  ax,[bp][Low1]
  mul  word [bp][Low2]

UnsMul8:
  and  ax,ax
UnsMul9:
  pop  bp
  ret  near  8

UnsMul1:
  cmp  word [bp][High2],0
  jnz  UnsMul0
  mul  word [bp][Low2]
  jmp  UnsMul3
UnsMul2:
  mul  word [bp][Low1]
UnsMul3:
  jc   UnsMul0
  mov  dx,[bp][Low1]
  mov  bp,[bp][Low2]
  xchg ax,bp
  mul  dx
  add  dx,bp
  jnc  UnsMul8

UnsMul0:
  mov  al,100
  add  al,al
  stc
  mov  ax,0FFFFH
  mov  dx,ax
  jmp  UnsMul9

section
segment _TEXT(CODE,28H);

public N$SgnMul : High1 = frame+6; Low1 = frame+4; High2 = frame+2; Low2 = frame
(*Signed multiplication *)
(*On overflow: result MAXINT, OF set *)
  push bp
  mov  bp,sp
  push si

  xor  si,si
  mov  dx,[bp][High1]
  and  dx,dx
  jge  SgnMul5
  not  si
  neg  dx
  neg  word [bp][Low1]
  sbb  dx,0
  mov  [bp][High1],dx
SgnMul5:
  mov  dx,[bp][High2]
  and  dx,dx
  jg   SgnMul6
  jz   SgnMul1
  not  si
  neg  dx
  neg  word [bp][Low2]
  sbb  dx,0
  jz   SgnMul1

SgnMul6:
  cmp  word [bp][High1],0
  jnz  SgnMul0
  mov  ax,dx
  mul  word [bp][Low1]
  jmp  SgnMul2
SgnMul1:
  mov  ax,[bp][High1]
  and  ax,ax
  jz   SgnMul2
  mul  word [bp][Low2]
SgnMul2:
  jc   SgnMul0
  mov  dx,[bp][Low1]
  mov  bp,[bp][Low2]
  xchg ax,bp
  mul  dx
  add  dx,bp
  jc   SgnMul0
  js   SgnMul0

  add  ax,si
  adc  dx,si
  xor  ax,si
  xor  dx,si

SgnMul7:
  pop  si
  pop  bp
  ret  near  8

SgnMul0:
  mov  al,100
  add  al,al
  mov  ax,0FFFFH
  mov  dx,07FFFH
  jmp  SgnMul7

section
segment _TEXT(CODE,28H);

public N$LngShl :
  xor  ch,ch
  jcxz $lshl1
$lshl2:
  shl  ax,1
  rcl  dx,1
  loop $lshl2
$lshl1:
  ret near  0

section
segment _TEXT(CODE,28H);

public  N$LngShr :
  xor  ch,ch
  jcxz  $lshr1
$lshr2:
  sar  dx,1
  rcr  ax,1
  loop $lshr2
$lshr1:
  ret  near  0

section
segment _TEXT(CODE,28H);

public  N$ULngShr :
  xor  ch,ch
  jcxz  $ulshr1
$ulshr2:  shr  dx,1
  rcr  ax,1
  loop  $ulshr2
$ulshr1:
  ret near  0

section
segment _TEXT(CODE,28H);

public  N$MovByt : SourceSeg =frame+8; SourceOff = frame+6; DestSeg = frame+4; DestOff = frame+2; Count = frame
  push bp
  mov  bp,sp
  push cx; push si; push di
  mov cx, [bp][Count]
  mov di, [bp][DestOff]
  mov si, [bp][SourceOff]
  rep; movsb;
  pop di; pop si; pop cx
  pop bp
  ret near  10

section
segment _TEXT(CODE,28H);

public  N$PushByt : SourceSeg = frame+4; SourceOff = frame+2; Count = frame
  push bp
  mov bp,sp
  sub sp, [bp][Count]
  push [bp][2] (* return ip *)
  push cx; push si; push di
  mov si, [bp][SourceOff]
  mov cx, [bp][Count]
  mov bp, [bp] (* restore bp *)
  mov di, sp
  add di, frame+frame+14
  rep; movsb
  pop di; pop si; pop cx
  ret near  frame+6

section
segment _TEXT(CODE,28H);

public  N$PopByt : Data = frame+6; DestSeg = frame+4; DestOff = frame+2; Count = frame
  push bp
  mov bp,sp
  push cx; push si; push di
  mov cx, [bp][Count]
  mov di, [bp][DestOff]
  lea si, [bp][Data]
  rep; movsb
  lea bp, [si][-frame]
  pop di; pop si; pop cx
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  ret near  0

section
segment _TEXT(CODE,28H);

public N$SetOr : Data = frame+2; Count = frame
  push bp
  mov bp, sp
  push ax; push bx; push cx; push si
  mov cx, [bp][Count]
  lea bp, [bp][Data]
  mov si, cx
$loop:
  mov al, [bp]
  or [bp][si], al
  inc bp
  loop $loop
  sub bp, frame
  pop si; pop cx; pop bx; pop ax
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  ret near 0

section
segment _TEXT(CODE,28H);

public N$SetDif : Data = frame+2; Count = frame
  push bp
  mov bp, sp
  push ax; push bx; push cx; push si
  mov cx, [bp][Count]
  lea bp, [bp][Data]
  mov si, cx
$loop:
  mov al, [bp]
  not al
  and [bp][si], al
  inc bp
  loop $loop
  sub bp, frame
  pop si; pop cx; pop bx; pop ax
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  ret near 0

section
segment _TEXT(CODE,28H);

public N$SetXor : Data = frame+2; Count = frame
  push bp
  mov bp, sp
  push ax; push bx; push cx; push si
  mov cx, [bp][Count]
  lea bp, [bp][Data]
  mov si, cx
$loop:
  mov al, [bp]
  xor [bp][si], al
  inc bp
  loop $loop
  sub bp, frame
  pop si; pop cx; pop bx; pop ax
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  ret near 0

section
segment _TEXT(CODE,28H);

public N$SetAnd : Data = frame+2; Count = frame
  push bp
  mov bp, sp
  push ax; push bx; push cx; push si
  mov cx, [bp][Count]
  lea bp, [bp][Data]
  mov si, cx
$loop:
  mov al, [bp]
  and [bp][si], al
  inc bp
  loop $loop
  sub bp, frame
  pop si; pop cx; pop bx; pop ax
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  ret near 0

section
segment _TEXT(CODE,28H);

public N$DupByt : Seg = frame+6; Off = frame+4; Data = frame+2; Count = frame
  push bp
  mov bp,sp
  push di; push cx; push ax
  mov al, [bp][Data]
  mov cx, [bp][Count]
  mov di, [bp][Off]
  mov ah, al
  shr cx,1
  rep; stosw
  jnc $DupBytExit
  stosb
$DupBytExit:
  pop ax; pop cx; pop di
  pop bp
  ret near 8

section
segment _TEXT(CODE,28H);

public N$EquByte : Data = frame+2; Count = frame
(* result in flags and ax *)
  push bp
  mov bp, sp
  push cx; push si; push di
  mov cx, [bp][Count]
  lea si, [bp][Data]
  mov di, si
  add di, cx
  mov bp, di
  add bp, cx
  repz; cmpsb
  pop di; pop si; pop cx (* pop was wrong order *)
  lea bp, [bp][-frame] (* build return link, preserve flags!!*)
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  mov ax,0
  jnz $not_equal
  mov al, 1
$not_equal:
  ret near 0

segment _TEXT(CODE,28H);

public N$NotEquByte : Data = frame+2; Count = frame
(* result in flags and ax *)
  push bp
  mov bp, sp
  push cx; push si; push di
  mov cx, [bp][Count]
  lea si, [bp][Data]
  mov di, si
  add di, cx
  mov bp, di
  add bp, cx
  repz; cmpsb
  pop di; pop si; pop cx (* pop was wrong order *)
  lea bp, [bp][-frame] (* build return link, preserve flags!!*)
  pop [bp]
  pop [bp][2]
  mov sp, bp
  pop bp
  mov ax,0
  jz  $equal
  inc ax
$equal:
  ret near  0

section
segment _TEXT(CODE,28H);

public N$HugeSub : p = frame+4; q = frame
  push bp
  mov bp, sp
  push bx; push cx
  mov ax, [bp][p]
  mov dx, [bp][p][2]
  mov bx, [bp][q][2]
  mov cx, DOSHUGESHIFT
  shr bx, cl
  shr dx, cl
  sub ax, [bp][q]
  sbb dx, bx
  pop cx; pop bx
  pop bp
  ret near  8

section
segment _TEXT(CODE,28H);

public  N$LngRol :
  push bx
  and  cx, 31
  cmp  cx, 16
  jb   $1
  sub cx, 16
  xchg ax,dx
$1:
  rol ax, cl
  rol dx, cl
  mov bx, 1
  rol bx, cl
  dec bx
  mov cx, ax
  xor cx, dx
  and cx, bx
  xor ax, cx
  xor dx, cx
  pop bx
  ret near  0

section
segment _TEXT(CODE,28H);

public N$SetRng : Start = frame+4; Stop = frame+2; Count = frame
  push bp
  mov bp, sp
  sub sp, [bp][Count]
  push [bp][2] (* return ip *)
  push ax; push bx; push cx; push dx; push si; push di
  mov bx, [bp][Count]
  mov si, [bp][Start]
  mov dx, [bp][Stop]
  mov bp, [bp]

  mov di, sp; add di, frame+frame+18

  add bx, di (*End*)
  mov ax, si (*Start*)
  cmp ax, dx (*Stop*)
  ja $lastpart

  mov cx, ax
  shr cx, 1; shr cx, 1; shr cx, 1
  sub al, al
  rep; stosb

  mov cl, si (*Start*)
  and cl, 7
  mov al, 0FFH
  shl al, cl
  stosb

  mov cx, dx (*Stop*)
  shr cx, 1; shr cx, 1; shr cx, 1
  mov ax, si (*Start*)
  shr ax, 1; shr ax, 1; shr ax, 1
  sub cx, ax
  jz $one_byte_non_zero
  dec cx
  mov al, 0FFH
  rep; stosb
$done_all_ones:
  mov cl, 7
  sub cl, dl (*Stop*)
  and cl, 7
  mov al, 0FFH
  shr al, cl
  stosb

$lastpart:
  mov cx, bx (*End*)
  sub cx, di
  sub al,al
  rep; stosb

  pop di; pop si; pop dx; pop cx; pop bx; pop ax;
  ret near  frame+6

$one_byte_non_zero:
  mov cl, 7
  sub cl, dl (*Stop*)
  and cl, 7
  mov al, 0FFH
  shr al, cl
  and es:[di][-1], al
  jmp $lastpart

section
segment _TEXT(CODE,28H);

extrn __FatalError
extrn __stk_base

IPVar = 0

public N$StkChk :

    add  bp, 100H
    cmp  sp, bp
    jb   stackError
    ret	 0
stackError:
    mov  bx, sp
    mov	 ax, ss:[bx][IPVar]
    mov  bx, FatalStackCheck
    jmp  __FatalError

section
segment _TEXT(CODE,28H);

extrn __FatalError
extrn  CoreSig@CnsHandler

IPVar = 8

public N$CnsStk :  push ax; mov ax,  1  ; jmp N$cns
public N$CnsPtr :  push ax; mov ax,  2  ; jmp N$cns
public N$CnsIdx :  push ax; mov ax,  9  ; jmp N$cns
public N$CnsOvr :  push ax; mov ax,  4  ; jmp N$cns
public N$CnsRng :  push ax; mov ax,  5  ; jmp N$cns
public N$CnsRet :  push ax; mov ax,  6  ; jmp N$cns
public N$CnsCase : push ax; mov ax,  7  ; jmp N$cns
public N$CnsDiv :  push ax; mov ax,  8  ; jmp N$cns
public N$CnsPVC :  push ax; mov ax, 0AH

N$cns:
    push bx
    push cx
    push dx
    mov  cx, ax
    mov  bx, sp
    mov	 ax, ss:[bx][IPVar]
    mov	 bx, cx
    cmp  word ss:[CoreSig@CnsHandler], 0
    je   noHandler
    call near ss:[CoreSig@CnsHandler]
    or   al, al
    jz	 noHandler
    pop  dx
    pop  cx
    pop  bx
    pop  ax
    ret  0
noHandler:
    jmp  __FatalError

end

